package com.mf.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.mf.entity.Log;
import com.mf.entity.Menu;
import com.mf.entity.Role;
import com.mf.entity.User;
import com.mf.service.LogService;
import com.mf.service.MenuService;
import com.mf.service.RoleService;
import com.mf.service.UserService;
import com.mf.util.StringUtil;

/**
 * 用户Controller
 * @author Administrator
 *
 */
@Controller
@RequestMapping("/user")
public class UserController {

	@Resource
	private UserService userService;
	
	@Resource
	private RoleService roleService;
	
	@Resource
	private MenuService menuService;
	
	@Resource
	private LogService logService;
	
	/**
	 * 用户登录判断
	 * @param imageCode
	 * @param user
	 * @param bindingResult
	 * @param session
	 * @return
	 */
	@ResponseBody
	@RequestMapping("/login")
	//后端字段加了验证  bingdingResult 和@Valid结合使用  规定逻辑在userpojo中
	public Map<String,Object> login(String imageCode,@Valid User user,BindingResult bindingResult,HttpSession session){
		Map<String,Object> map=new HashMap<String,Object>();
		if(StringUtil.isEmpty(imageCode)){//判断是否为空
			map.put("success", false);
			map.put("errorInfo", "请输入验证码!");
			return map;
		}
		if(!session.getAttribute("checkcode").equals(imageCode)){//？？？？
			map.put("success", false);
			map.put("errorInfo", "验证码输入错误!");
			return map;
		}
		if(bindingResult.hasErrors()){
			map.put("success", false);
			//返回错误信息
			map.put("errorInfo", bindingResult.getFieldError().getDefaultMessage());
			return map;
		}
		Subject subject=SecurityUtils.getSubject();
		UsernamePasswordToken token=new UsernamePasswordToken(user.getUserName(), user.getPassword());
		try{//传入的是username和password
			subject.login(token);//验证登陆
			//这边应该做一个判断  而不是直接去取username （当然如果直接取会报异常）
			String userName=(String) SecurityUtils.getSubject().getPrincipal();
			User currentUser=userService.findByUserName(userName);//这里和Realm一样只是查t_uesr
			session.setAttribute("currentUser", currentUser);//把用户存进去
			List<Role> roleList=roleService.findByUserId(currentUser.getId());//最后查到role*表
			map.put("roleList", roleList);
			map.put("roleSize", roleList.size());
			map.put("success", true);//只有这里给的是true
			logService.save(new Log(Log.LOGIN_ACTION,"用户登录"));
			return map;
		}catch(Exception e){
			e.printStackTrace();
			map.put("success", false);
			map.put("errorInfo", "用户名或者密码错误!");
			return map;
		}
	}
	
	/**
	 * 保存角色信息
	 * @param roleId
	 * @param session
	 * @return
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping("/saveRole")
	public Map<String,Object> saveRole(Integer roleId,HttpSession session)throws Exception{
		Map<String,Object> map=new HashMap<String,Object>();
		Role currentRole=roleService.findById(roleId);//获取id对应的行
		session.setAttribute("currentRole", currentRole);
		map.put("success", true);
		return map;
	}
	
	/**
	 * 加载当前用户信息
	 * @param session
	 * @return
	 * @throws Exception
	 */
	@ResponseBody
	@GetMapping("/loadUserInfo")
	//固定返回页面头部信息  获取user和role （这里只有一个role就是用户选择的）
	public String loadUserInfo(HttpSession session)throws Exception{
		User currentUser=(User) session.getAttribute("currentUser");
		Role currentRole=(Role) session.getAttribute("currentRole");
		return "欢迎您："+currentUser.getTrueName()+"&nbsp;[&nbsp;"+currentRole.getName()+"&nbsp;]";
	}
	
	/**
	 * 加载权限菜单
	 * @param session
	 * @param parentId
	 * @return
	 * @throws Exception
	 */
	@ResponseBody
	@PostMapping("/loadMenuInfo")
	//登陆确认后
	public String loadMenuInfo(HttpSession session,Integer parentId)throws Exception{
		Role currentRole=(Role) session.getAttribute("currentRole");
		return getAllMenuByParentId(parentId,currentRole.getId()).toString();
	}
	
	/**
	 * 获取所有菜单信息
	 * @param parentId
	 * @param roleId
	 * @return
	 */
	public JsonArray getAllMenuByParentId(Integer parentId,Integer roleId){
		JsonArray jsonArray=this.getMenuByParentId(parentId, roleId);
		for(int i=0;i<jsonArray.size();i++){
			JsonObject jsonObject=(JsonObject) jsonArray.get(i);
			if("open".equals(jsonObject.get("state").getAsString())){
				continue;//如果是子节点跳过 反之是主节点添加子节点
			}else{
				//获取本一级的id作为parentid   .getAsInt()  JSON获取某个key的value
				//重点！！！！递归查询
				jsonObject.add("children", getAllMenuByParentId(jsonObject.get("id").getAsInt(), roleId));
			}
		}
		return jsonArray;
	}
	
	/**
	 * 根据父节点和用户角色Id查询菜单
	 * @param parentId
	 * @param roleId
	 * @return
	 */
	//这一级是最高级出现系统菜单  每个角色都会触发
	//递归多级被利用了 这个方法要走多遍
	public JsonArray getMenuByParentId(Integer parentId,Integer roleId){
		List<Menu> menuList=menuService.findByParentIdAndRoleId(parentId, roleId);
		JsonArray jsonArray=new JsonArray();
		for(Menu menu:menuList){
			JsonObject jsonObject=new JsonObject();
			jsonObject.addProperty("id", menu.getId()); // 节点Id
			jsonObject.addProperty("text", menu.getName()); // 节点名称
			if(menu.getState()==1){
				jsonObject.addProperty("state", "closed"); // 根节点
			}else{
				jsonObject.addProperty("state", "open"); // 叶子节点
			}
			jsonObject.addProperty("iconCls", menu.getIcon()); // 节点图标
			JsonObject attributeObject=new JsonObject(); // 扩展属性
			attributeObject.addProperty("url", menu.getUrl()); // 菜单请求地址
			jsonObject.add("attributes", attributeObject); 
			jsonArray.add(jsonObject);
		}
		return jsonArray;
	}
}
